﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BEPUphysics.Entities;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using MagicArenaXNA.ControllerInput.Bepu;
using BEPUphysics.MathExtensions;
using Networking;
using Networking.Packets;

namespace MagicArenaFramework.GameObject.Components.ConcreteTypes
{
    public class ControllerComponent : GoComponent
    {
        public SimpleCharacterController Controller { get; private set; }

        public ControllerComponent(SimpleCharacterController controller)
        {
            Controller = controller;
            this.UpdateDel = MyUpdate;
        }

        public override bool isActive
        {
            get
            {
                return base.isActive;
            }
            set
            {
                if (isActive != value)
                {
                    if (value) Controller.Activate();
                    else Controller.Deactivate();
                }
                base.isActive = value;
            }
        }

        private KeyboardState previousKeyboardInput;
        void MyUpdate(float dt)
        {
            //Note that the character controller's update method is not called here; this is because it is handled within its owning space.
            //This method's job is simply to tell the character to move around based on the Camera and input.

            //Get keyboard input
            KeyboardState keyboardInput = Keyboard.GetState();

            //Puts the Camera at eye level.
            

            Vector2 totalMovement = Vector2.Zero;
#if !WINDOWS //Not functional, left in in case I decide to do xbox later for some reason
                Vector3 forward = Camera.WorldMatrix.Forward;
                forward.Y = 0;
                forward.Normalize();
                Vector3 right = Camera.WorldMatrix.Right;
                totalMovement += gamePadInput.ThumbSticks.Left.Y * new Vector2(forward.X, forward.Z);
                totalMovement += gamePadInput.ThumbSticks.Left.X * new Vector2(right.X, right.Z);
                Controller.MovementDirection = Vector2.Normalize(totalMovement);

                //Jumping
                if (previousGamePadInput.IsButtonUp(Buttons.LeftStick) && gamePadInput.IsButtonDown(Buttons.LeftStick))
                {
                    Controller.Jump();
                }
#else
            //Collect the movement impulses.
            Vector3 movementDir;
            float angularVel=0;
            const float angularVelAmount=0.8f;

            if (keyboardInput.IsKeyDown(Keys.S))
            {
                movementDir = Controller.Body.WorldTransform.Backward;
                totalMovement += Vector2.Normalize(new Vector2(movementDir.X, movementDir.Z));
            }
            if (keyboardInput.IsKeyDown(Keys.W))
            {
                movementDir = Controller.Body.WorldTransform.Forward;
                totalMovement += Vector2.Normalize(new Vector2(movementDir.X, movementDir.Z));
            }
            if (keyboardInput.IsKeyDown(Keys.Q))
            {
                movementDir = Controller.Body.WorldTransform.Left;
                totalMovement += Vector2.Normalize(new Vector2(movementDir.X, movementDir.Z));
            }
            if (keyboardInput.IsKeyDown(Keys.E))
            {
                movementDir = Controller.Body.WorldTransform.Right;
                totalMovement += Vector2.Normalize(new Vector2(movementDir.X, movementDir.Z));
            }
            if (keyboardInput.IsKeyDown(Keys.A))
            {
                angularVel +=angularVelAmount;
            }
            if (keyboardInput.IsKeyDown(Keys.D))
            {
                angularVel -= angularVelAmount;
            }

            if (totalMovement == Vector2.Zero)
                Controller.MovementDirection = Vector2.Zero;
            else
                Controller.MovementDirection = Vector2.Normalize(totalMovement);
            if (angularVel == 0)
                Controller.Body.AngularVelocity = Vector3.Zero;
            else
                Controller.Body.AngularVelocity = new Vector3(0, angularVel, 0);

            
            //Jumping
            if (previousKeyboardInput.IsKeyUp(Keys.Space) && keyboardInput.IsKeyDown(Keys.Space))
            {
                 Controller.Jump();
            }


#endif
            
        }
    }

    public class ControllerRemote : GoComponent
    {
        public Entity Entity { get; private set; }
        private SimpleGameClient Client;
        public UInt64 Gid { get; private set; }

        public ControllerRemote(Entity entityToControl, UInt64 gid, SimpleGameClient client)
        {
            Entity = entityToControl;
            Client = client;
            Gid = gid;
            this.UpdateDel = MyUpdate;
        }

        void MyUpdate(float dt)
        {
            LocationPacket l = Client.LocationPackets.Find(FindLocation);
            if (l != null)
            {
                Entity.Position = l.Location;
                Entity.Orientation = l.Orientation;
            }

        }

        bool FindLocation(LocationPacket loc)
        {
            return loc.PlayerID == Gid;
        }

    }
}
